﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using Equation.Enterprise.Framework.Web.Model;

namespace ENail.Portal.Web.Controllers
{
    public abstract class DUALController<TListViewItem, 
                                TViewModel,
                                TDomainModel> : BaseController
                                where TViewModel : new()
                                where TDomainModel : new()
    {
        protected string ListViewName { get; set; }
        protected string ViewName { get; set; }
        protected ListViewModelMapper<TListViewItem, TDomainModel> ListMapper { get; set; }
        protected ViewModelMapper<TViewModel, TDomainModel> Mapper { get; set; }

        public DUALController(string listViewName,
                              string viewName,
                              ListViewModelMapper<TListViewItem, TDomainModel> listMapper,
                              ViewModelMapper<TViewModel, TDomainModel> mapper)
        {
            ListViewName = listViewName;
            ViewName = viewName;
            ListMapper = listMapper;
            Mapper = mapper;
        }

        public ActionResult List(int? page, string filter)
        {
            List<TDomainModel> domainModel = GetList();
            GenericListViewModel<TListViewItem> viewModel = new GenericListViewModel<TListViewItem>();
            viewModel.Page = page;
            viewModel.Filter = filter;

            ListMapper.MapDomainToView(domainModel, viewModel);

            return View(ListViewName, viewModel);
        }

        [HttpPost]
        public ActionResult List(GenericListViewModel<TListViewItem> model)
        {
            return List(null, model.Filter);
        }

        [HttpGet]
        public ActionResult Add()
        {
            TDomainModel domainModel = new TDomainModel();
            TViewModel viewModel = new TViewModel();
            Mapper.MapDomainToView(domainModel, viewModel);

            return View(ViewName, viewModel);
        }

        [HttpPost]
        public ActionResult Add(TViewModel model)
        {
            if (!ModelState.IsValid)
            {
                Mapper.ReMap(model);
                return View(ViewName, model);
            }

            TDomainModel domainModel = new TDomainModel();
            Mapper.MapViewToDomain(model, domainModel);
            Add(domainModel);

            return RedirectToAction("List");
        }

        [HttpGet]
        public ActionResult Update(int id)
        {
            TDomainModel domainModel = Get(id);
            TViewModel viewModel = new TViewModel();
            Mapper.MapDomainToView(domainModel, viewModel);

            return View(ViewName, viewModel);
        }

        [HttpPost]
        public ActionResult Update(int id, TViewModel model)
        {
            if (!ModelState.IsValid)
            {
                Mapper.ReMap(model);
                return View(ViewName, model);
            }

            TDomainModel domainModel = Get(id);
            Mapper.MapViewToDomain(model, domainModel);
            Update(domainModel);

            return RedirectToAction("List");
        }

        [HttpPost]
        public ActionResult Delete(int id)
        {
            TDomainModel domainModel = Get(id);
            Delete(domainModel);

            return RedirectToAction("List");
        }

        protected abstract List<TDomainModel> GetList();
        protected abstract TDomainModel Get(int id);
        protected abstract void Add(TDomainModel domainModel);
        protected abstract void Update(TDomainModel domainModel);
        protected abstract void Delete(TDomainModel domainModel);
    }
}